/*
 * Licensed under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.submarine.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @file org.submarine.util.CalendarUtil.java
 *
 * 日期时间工具类
 * 
 * @author gaojian
 * @created 2013-8-17 下午11:49:39
 * @version 0.0.1
 * @since 0.0.1
 * 
 */
public final class CalendarUtil {

	private CalendarUtil() {}
	
	private static final Map<String, ThreadLocal<SimpleDateFormat>> timestampFormatPool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();  
	
	private static final Map<String, ThreadLocal<SimpleDateFormat>> dateFormatPool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();  

	private static final Object timestampFormatLock = new Object(); 
	
	private static final Object dateFormatLock = new Object(); 
	
	private static String dateFormatPattern = "yyyy-MM-dd";
	
	private static String timestampPattern = "yyyy-MM-dd HH:mm:ss";
	
	private static SimpleDateFormat getDateFormat() {
		ThreadLocal<SimpleDateFormat> tl = dateFormatPool.get(dateFormatPattern);
		if (null == tl) {
			synchronized (dateFormatLock) {
				tl = dateFormatPool.get(dateFormatPattern);
				if (null == tl) {
					tl = new ThreadLocal<SimpleDateFormat>() {
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(dateFormatPattern);
						}
					};
					dateFormatPool.put(dateFormatPattern, tl);
				}
			}
		}
		return tl.get();
	}
	
	private static SimpleDateFormat getTimestampFormat() {
		ThreadLocal<SimpleDateFormat> tl = timestampFormatPool.get(timestampPattern);
		if (null == tl) {
			synchronized (timestampFormatLock) {
				tl = timestampFormatPool.get(timestampPattern);
				if (null == tl) {
					tl = new ThreadLocal<SimpleDateFormat>() {
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(timestampPattern);
						}
					};
					timestampFormatPool.put(timestampPattern, tl);
				}
			}
		}
		return tl.get();
	}
	
	/**
	 * 
	 * 格式化成时间戳格式
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午4:58:36
	 *
	 * @param date	要格式化的日期
	 * @return	"年年年年-月月-日日 时时:分分:秒秒"格式的日期字符串
	 */
	public static String timestampFormat(Date date){
		if(date == null){
			return "";
		}
		return getTimestampFormat().format(date);
	}
	
	/**
	 * 
	 * 格式化成时间戳格式
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午4:58:59
	 *
	 * @param datetime	要格式化的日期
	 * @return	"年年年年-月月-日日 时时:分分:秒秒"格式的日期字符串
	 */
	public static String timestampFormat(long datetime){
		return getTimestampFormat().format(new Date(datetime));
	}
	
	/**
	 * 
	 * 将"年年年年-月月-日日 时时:分分:秒秒"格式的日期字符串转换成Long型日期
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午4:59:16
	 *
	 * @param timestampStr	年年年年-月月-日日 时时:分分:秒秒"格式的日期字符串
	 * @return	Long型日期
	 */
	public static long formatTimestampToLong(String timestampStr){
		Date date;
		try {
			date = getTimestampFormat().parse(timestampStr);
		} catch (ParseException e) {
			return 0L;
		}
		return date.getTime();
	}
	
	/**
	 * 
	 * 格式化成日期格式
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午4:59:41
	 *
	 * @param date	要格式化的日期
	 * @return	"年年年年-月月-日日"格式的日期字符串
	 */
	public static String dateFormat(Date date){
		if(date == null){
			return "";
		}
		return getDateFormat().format(date);
	}
	
	/**
	 * 
	 * 格式化成日期格式
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午4:59:54
	 *
	 * @param datetime	要格式化的日期
	 * @return	"年年年年-月月-日日"格式的日期字符串
	 */
	public static String dateFormat(long datetime){
		return getDateFormat().format(new Date(datetime));
	}
	
	/**
	 * 
	 * 将"年年年年-月月-日日"格式的日期字符串转换成Long型日期
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:00:12
	 *
	 * @param dateStr	"年年年年-月月-日日"格式的日期字符串
	 * @return	Long型日期
	 * @throws IllegalArgumentException	日期格式化异常
	 */
	public static long formatDateToLong(String dateStr) throws IllegalArgumentException {
		Date date;
		try {
			date = getDateFormat().parse(dateStr);
		} catch (ParseException e) {
			throw new IllegalArgumentException("将输入内容格式化成日期类型时出错。", e);
		}
		return date.getTime();
	}
	


	/**
	 * 
     * 得到本月的第一天
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:00:38
	 *
     * @return	以"年年年年-月月-日日"格式返回当前月第一天的日期
	 */
    public static String getFirstDayOfCurrentMonth() {   
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar
                .getActualMinimum(Calendar.DAY_OF_MONTH));
        return getDateFormat().format(calendar.getTime());
    }   

    /**
     * 
     * 得到本月的最后一天 
     *
     * @author gaojian
     * @created 2013-8-19 下午5:00:54
     *
     * @return	以"年年年年-月月-日日"格式返回当前月最后一天的日期
     */
    public static String getLastDayOfCurrentMonth() {   
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return getDateFormat().format(calendar.getTime());
    }
    
    /**
     * 
     * 获取指定日期所在月的第一天
     *
     * @author gaojian
     * @created 2013-8-19 下午5:01:11
     *
     * @param date	日期
     * @return	以"年年年年-月月-日日"格式返回当指定月第一天的日期
     */
    public static String getFirstDayOfMonth(Date date) {   
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.set(Calendar.DAY_OF_MONTH, 1);
		return getDateFormat().format(ca.getTime());
    }   
    
    /**
     * 
     * 获取指定日期所在月的最后一天
     *
     * @author gaojian
     * @created 2013-8-19 下午5:01:27
     *
     * @param date
     * @return	以"年年年年-月月-日日"格式返回当指定月最后一天的日期
     */
    public static String getLastDayOfMonth(Date date) {   
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.set(Calendar.DAY_OF_MONTH, 1);
		ca.roll(Calendar.DAY_OF_MONTH, -1);
		return getDateFormat().format(ca.getTime());
    }
    
    /**
     * 
     * 获取指定日期所在周的第一天
     *
     * @author gaojian
     * @created 2013-8-19 下午5:01:43
     *
     * @param date	日期
     * @return	以"年年年年-月月-日日"格式返回当指定周第一天的日期
     */
    public static String getFirstDayOfWeek(Date date) {   
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.set(Calendar.DAY_OF_WEEK, 2);
		return getDateFormat().format(ca.getTime());
    }   
    
    /**
     * 
     * 获取指定日期所在月的最后一天
     *
     * @author gaojian
     * @created 2013-8-19 下午5:02:03
     *
     * @param date
     * @return	以"年年年年-月月-日日"格式返回当指定周最后一天的日期
     */
    public static String getLastDayOfWeek(Date date) {   
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.set(Calendar.DAY_OF_WEEK, 2);
		ca.set(Calendar.DAY_OF_WEEK, -1);
		ca.add(Calendar.DATE, 2);
		return getDateFormat().format(ca.getTime());
    }
    
    /**
     * 
     * 获取当前日期的前一天
     *
     * @author gaojian
     * @created 2013-8-19 下午5:02:20
     *
     * @return	以"年年年年-月月-日日"格式返回当前日期的前一天的日期
     */
	public static String getDayBeforeCurrentDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, -1);
		return getDateFormat().format(calendar.getTime());
	}
	
	/**
	 * 
	 * 获取指定日期的前一天
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:02:36
	 *
	 * @param date
	 * @return	以"年年年年-月月-日日"格式返回指定日期的前一天的日期
	 */
	public static String getDayBeforeDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, -1);
		return getDateFormat().format(calendar.getTime());
	}
	
	/**
	 * 
	 * 获取当前日期的后一天
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:02:55
	 *
	 * @return	以"年年年年-月月-日日"格式返回当前日期的后一天的日期
	 */
	public static String getDayAfterCurrentDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, 1);
		return getDateFormat().format(calendar.getTime());
	}
	
	/**
	 * 
	 * 获取当前日期的后一天
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:03:11
	 *
	 * @param date
	 * @return	以"年年年年-月月-日日"格式返回指定日期的后一天的日期
	 */
	public static String getDayAfterDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, 1);
		return getDateFormat().format(calendar.getTime());
	}
	
	/**
	 * 
     * 获取当前时间，精确到秒
	 *
	 * @author gaojian
	 * @created 2013-8-19 下午5:03:38
	 *
     * @return	精确到秒的当前时间
	 */
    public static int currentTimeSecond(){
        return Long.valueOf(System.currentTimeMillis()/1000).intValue();
    }
    
    /**
     * 
     * 替换掉日期格式中所有分隔符（含“-”、“:”及空格）
     *
     * @author gaojian
     * @created 2013-8-19 下午5:04:15
     *
     * @param target	字符型目标日期
     * @return	替换后的结果
     */
    public static String replaceAllSeparator(String target) {
    	return target.replace("-", "").replace(":", "").replace(" ", "");
    }
    
    /**
     * 
     * 替换掉日志格式中指定的分隔符
     *
     * @author gaojian
     * @created 2013-8-19 下午5:04:31
     *
     * @param target	字符型目标日期
     * @param separator	要被替换掉的分割符
     * @return	替换后的结果
     */
    public static String replaceSeparator(String target, String... separator) {
    	String temp = target;
    	for (String sep : separator) {
    		temp = temp.replace(sep, "");
    	}
    	return temp;
    }
	
	
}
